<template>
  <el-table ref="el_table" v-if="cols" :data="data" @cell-click="cell_click" @selection-change="select_change" @sort-change="sort_change" border stripe :header-cell-style="{background: 'var(--bg)'}" :row-class-name="row_class" :cell-class-name="cell_class" style="width: 100%">

    <template #default>
      <el-table-column v-if="has_select" type="selection" width="30" align="center" fixed="left"></el-table-column>
      <template v-for="col in cols">
        <el-table-column v-if="col.type != 'hidden'" v-bind="bind_param_col(col)">
          <template #default="scope">
            <template v-if="$slots[col.type]">
              <slot :name="col.type" :row="scope.row" :col="col" :index="scope.$index"></slot>
            </template>
            <unite-param v-else :_type_="col.type" :model-value="scope.row[col.name]" :_props_="bind_param_cell(scope.row, col)" @change="onchange(scope.row, col,$event)"></unite-param>

          </template>
        </el-table-column>
      </template>
    </template>

    <template #append>
      <div ref="bottom_row" class="bottom_row" v-show="!is_over" style="justify-content: center;">&nbsp;</div>
    </template>
  </el-table>
  <dl v-else class="list_outer flex" ref="list_outer">
    <dd v-for="(row,index) in data">
      <slot name="list_row" :row="row" :index="index" :is_select="!!~selected.indexOf(row)" :select_toggle="select_toggle"></slot>
    </dd>
    <dd ref="bottom_row" class="bottom_row" v-show="!is_over" style="justify-content: center;">&nbsp;</dd>
  </dl>
</template>

<script>
import {bind_param, field_type} from "@/js/tool.js";
import s94_param from "@/components/s94_param.vue";
import UnifyParam from "@/components/auto_import/UnifyParam.vue";

export default {
  name: "list",
  components: {UniteParam: UnifyParam, s94_param},
  props: ['data','cols','has_select','order','scroll_bottom','row_class','cell_class'], // 表格滚动到底部时，执行 scroll_bottom 方法，方法返回的值表示是否加载完成
  emits: ['select:list','update:order'],
  data(){
    let default_sort = {};
    if (this.order) {
      let arr = this.order.split(' ');
      default_sort['prop'] = arr[0];
      default_sort['order'] = ((arr[1] || 'asc')+'ending').toLowerCase();
    }
    return {
      selected: [],
      is_append: false,
      is_over: false,
      default_sort: default_sort,

      scroll_timer: undefined,
    }
  },
  methods: {
    topx(v){
      v = v ? (v+'') : '';
      let str = v.replace(/([\d\.]+)rem/, '($1*rem)').
      replace(/(\d+)px/, '$1');
      return (new Function('rem','return '+str))(100);
    },
    is_component(type){
      let map = field_type();
      return type in map;
    },
    bind_param_col(col){
      let res = {
        label: col.label,
        prop: col.name,
        align: col.align || 'center',
        sortable: col.order ? 'custom' : false,
        width: this.topx(col.width),
        'min-width': this.topx(col['min_width'] || '60'),
      };
      if (col.fixed) res.fixed = col.fixed;
      return res;
    },
    bind_param_cell(row, col){
      let res = {
        is_info: (col.is_info || !col.can_edit),
        is_list: true,
      }
      if(/^list_ids?$/.test(col.type)) res['no_table'] = 1;

      return bind_param(Object.assign(res, col));
    },
    async onchange(row,col,v){
      if (typeof(col.onchange) == 'function'){
        let res = await col.onchange(row,col,v);
        if (res === false) return
      }
      row[col.name] = v;
    },
    select_change(selected){
      this.selected = selected;
      this.$emit('select:list', this.selected);
    },
    select_toggle(row){
      let i = this.selected.indexOf(row);
      if (i == -1){
        this.selected.push(row)
      }else {
        this.selected.splice(i,1);
      }
      this.$emit('select:list', this.selected);
    },
    sort_change(data){
      let order = '';
      if (data.order) {
        order = data.prop+' '+data.order.replace('ending','')
      }
      this.$emit('update:order', order);
    },
    cell_click(row, column, cell, event){
      if (column.type == "selection") this.$refs.el_table.toggleRowSelection(row);
    },
    bottomListener(){
      let outerDom = this.$refs.el_table?.$el || this.$refs.list_outer;

      const observer = new IntersectionObserver((entries) => {
        if (!entries[0].isIntersecting || typeof this.scroll_bottom !== 'function') return ;

        Promise.resolve(this.scroll_bottom()).then(res => {
          this.is_over = res===false;
        })
      }, {
        root: outerDom,
      });
      let bottomDom = this.$refs.bottom_row;
      observer.observe(bottomDom);
      return observer;
    },
  },
  watch: {
    data(v,oldV){
      this.select_change([]);
    },
  },
  computed: {

  },
  mounted() {
    let app = this;

    // 监听是否滚动到底部
    this.observer = this.bottomListener();

  },
  unmounted() {
    if (this.observer) this.observer.disconnect();
    this.observer = null;
  },
  beforeDestroy(){
    let app = this;
  }

}
</script>

<style scoped>
.list_outer{width: 100%;flex-wrap: wrap;align-items: flex-start;justify-content: flex-start;align-content:flex-start;overflow: auto;}
.bottom_row{width: 100%;text-align: center;}
</style>